package dev.selenium.actions_api

import dev.selenium.BaseTest
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.openqa.selenium.By
import org.openqa.selenium.Rectangle
import org.openqa.selenium.WebElement
import org.openqa.selenium.interactions.Actions
import org.openqa.selenium.interactions.PointerInput
import org.openqa.selenium.interactions.Sequence
import org.openqa.selenium.remote.RemoteWebDriver

import kotlin.collections.Map
import java.time.Duration

class PenTest : BaseTest() {
  
    @Test
    fun usePen() {
        driver.get("https://www.selenium.dev/selenium/web/pointerActionsPage.html")
        
        val pointerArea = driver.findElement(By.id("pointerArea"))
        Actions(driver)
                .setActivePointer(PointerInput.Kind.PEN, "default pen")
                .moveToElement(pointerArea)
                .clickAndHold()
                .moveByOffset(2, 2)
                .release()
                .perform()

        val moves = driver.findElements(By.className("pointermove"))
        val moveTo = getPropertyInfo(moves.get(0))
        val down = getPropertyInfo(driver.findElement(By.className("pointerdown")))
        val moveBy = getPropertyInfo(moves.get(1))
        val up = getPropertyInfo(driver.findElement(By.className("pointerup")))
        
        val rect = pointerArea.getRect()

        val centerX = Math.floor(rect.width.toDouble() / 2 + rect.getX()).toInt()
        val centerY = Math.floor(rect.height.toDouble() / 2 + rect.getY()).toInt()
        Assertions.assertEquals("-1", moveTo.get("button"))
        Assertions.assertEquals("pen", moveTo.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), moveTo.get("pageX"))
        Assertions.assertEquals(centerY.toString(), moveTo.get("pageY"))
        Assertions.assertEquals("0", down.get("button"))
        Assertions.assertEquals("pen", down.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), down.get("pageX"))
        Assertions.assertEquals(centerY.toString(), down.get("pageY"))
        Assertions.assertEquals("-1", moveBy.get("button"))
        Assertions.assertEquals("pen", moveBy.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), moveBy.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), moveBy.get("pageY"))
        Assertions.assertEquals("0", up.get("button"))
        Assertions.assertEquals("pen", up.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), up.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), up.get("pageY"))
    }

    @Test
    fun setPointerEventProperties() {
        driver.get("https://selenium.dev/selenium/web/pointerActionsPage.html")
        
        val pointerArea = driver.findElement(By.id("pointerArea"))
        val pen = PointerInput(PointerInput.Kind.PEN, "default pen")
        val eventProperties = PointerInput.eventProperties()
                .setTiltX(-72)
                .setTiltY(9)
                .setTwist(86)
        val origin = PointerInput.Origin.fromElement(pointerArea)
        
        val actionListPen = Sequence(pen, 0)
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 0, 0))
                .addAction(pen.createPointerDown(0))
                .addAction(pen.createPointerMove(Duration.ZERO, origin, 2, 2, eventProperties))
                .addAction(pen.createPointerUp(0))

        (driver as RemoteWebDriver).perform(listOf(actionListPen))
                    

        val moves = driver.findElements(By.className("pointermove"))
        val moveTo = getPropertyInfo(moves.get(0))
        val down = getPropertyInfo(driver.findElement(By.className("pointerdown")))
        val moveBy = getPropertyInfo(moves.get(1))
        val up = getPropertyInfo(driver.findElement(By.className("pointerup")))
        
        val rect = pointerArea.getRect()

        val centerX = Math.floor(rect.width.toDouble() / 2 + rect.getX()).toInt()
        val centerY = Math.floor(rect.height.toDouble() / 2 + rect.getY()).toInt()
        Assertions.assertEquals("-1", moveTo.get("button"))
        Assertions.assertEquals("pen", moveTo.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), moveTo.get("pageX"))
        Assertions.assertEquals(centerY.toString(), moveTo.get("pageY"))
        Assertions.assertEquals("0", down.get("button"))
        Assertions.assertEquals("pen", down.get("pointerType"))
        Assertions.assertEquals(centerX.toString(), down.get("pageX"))
        Assertions.assertEquals(centerY.toString(), down.get("pageY"))
        Assertions.assertEquals("-1", moveBy.get("button"))
        Assertions.assertEquals("pen", moveBy.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), moveBy.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), moveBy.get("pageY"))
        Assertions.assertEquals("0", up.get("button"))
        Assertions.assertEquals("pen", up.get("pointerType"))
        Assertions.assertEquals((centerX + 2).toString(), up.get("pageX"))
        Assertions.assertEquals((centerY + 2).toString(), up.get("pageY")) 
	    
        Assertions.assertEquals("-72", moveBy.get("tiltX"))
        Assertions.assertEquals("9", moveBy.get("tiltY"))
        Assertions.assertEquals("86", moveBy.get("twist"))
    }
    
    fun getPropertyInfo(element: WebElement): Map<String, String> {
        var text = element.getText()  
        text = text.substring(text.indexOf(" ")+1)
        return text.split(", ")
        .map { it.split(": ") }
        .map { it.first() to it.last() }
        .toMap() 
    }
}